<?php

define('DS', DIRECTORY_SEPARATOR);

require __DIR__  . DS . 'async_socket_lib.php';


/**
 * @param      $host
 * @param      $port
 * @param      $method
 * @param      $data
 * @param bool $noBlocking
 * @return bool|false|string
 */
function asyncCheckClient($host, $port, $method, $data, $noBlocking = true)
{

    $client = new AsyncTcpClient();
    $client->connection($host, $port);
    fwrite(STDOUT, "\nconnect to server: [{$host}:{$port}]...\n");

    $message = json_encode([
        "method" => $method,
        "data" => $data
    ]);

    fwrite(STDOUT, "send to server: $message\n");
    $len = $client->send($message);
    if ($len === 0) {
        fwrite(STDOUT, "socket closed\n");
        return false;
    }

    if ($noBlocking) {
        // 非阻塞方式, 不等结果，之间返回调用成功
        return true;
    } else {
        // 阻塞方式，等待响应，读取后返回
        $msg = $client->response( 4096);
        return $msg;
    }
}

/**
 * 发起请求
 *
 * @param integer   $productId   产品ID
 * @param bool      $noBlocking      阻塞与否
 *
 * @return bool|false|string
 */
function asyncCheckInventory($productId, $noBlocking = true)
{
    // client.php
    $host = "127.0.0.1";
    $port = 8081;

    $data = array('productId' => $productId);

    return asyncCheckClient($host, $port, 'inventory', $data, $noBlocking);
}

/**
 * 检查产品可售
 *
 * @param      $productId
 * @param bool $noBlocking
 * @return bool|false|string
 */
function asyncCheckProduct($productId, $noBlocking = true)
{
    // client.php
    $host = "127.0.0.1";
    $port = 8082;

    $data = array('productId' => $productId);

    return asyncCheckClient($host, $port, 'product', $data, $noBlocking);
}

/**
 * 检查促销信息
 *
 * @param      $productId
 * @param bool $noBlocking
 * @return bool|false|string
 */
function asyncCheckPromo($productId, $noBlocking = true)
{
    // client.php
    $host = "127.0.0.1";
    $port = 8083;

    $data = array('productId' => $productId);

    return asyncCheckClient($host, $port, 'promo', $data,  $noBlocking);
}

$host = '0.0.0.0';
$port = 8080;

$server = new AsyncTcpServer($host, $port);

$server->on('accept', function(AsyncTcpServer $server, $socket, $info) {
    $server->console('accept a new client~' . PHP_EOL);
});

$server->on('receive', function(AsyncTcpServer $server, $socket, $info, $data) {
    $server->console('received data :' . $data . ' from : ' . strval($socket) . PHP_EOL);

    // 业务
    $dataArr = json_decode($data, true);
    $method = $dataArr["method"];
    $noBlocking = boolval($dataArr['noBlocking']);
    $productId = $dataArr['data']['productId'];

    $noBlocking = false;
    $checkAllSuc = false;

    // 依次发起三个检查请求
    $requestInventorySuc = Async::call( 'asyncCheckInventory', $productId, $noBlocking);
    $requestProductSuc = Async::call( 'asyncCheckProduct', $productId, $noBlocking);
    $requestPromoSuc = Async::call('asyncCheckPromo', $productId, $noBlocking);

    list($requestInventoryRe, $requestProductRe, $requestPromoRe) =
        (yield from Async::all($requestInventorySuc, $requestProductSuc, $requestPromoSuc));

    $inventoryData = json_decode($requestInventoryRe, true);
    $productData = json_decode($requestProductRe, true);
    $promoData = json_decode($requestPromoRe, true);
    $checkAllSuc = $inventoryData['data']['re'] && $productData['data']['re'] && $promoData['data']['re'];

    $reMsg = array('method' => 'cart', 'data' => array('product_id' => $productId), 're' => $checkAllSuc, 'msg' => 'suc');
    $reData = json_encode($reMsg);
    fwrite($socket, $reData . PHP_EOL);
    $server->console( 'response request: ' . strval($socket) . ' , data: ' . $reData . PHP_EOL . PHP_EOL);
    // 响应客户端后，关闭连接，并把它的socket从 select 去移除
    $server->close($socket);
});

$server->on('close', function(AsyncTcpServer $server, $socket, $info) {
    $server->console('client :' . strval($socket) . ' closed.' . PHP_EOL);
});

//$server->run();

EventLoop::inst()->addServerHandlers($server)->init()->loop();